package com.eastfair.venuebooking.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.venuebooking.dao.BusinessOpportunityMapper;
import com.eastfair.venuebooking.dto.*;
import com.eastfair.venuebooking.entity.*;
import com.eastfair.venuebooking.enumeration.ExhibitionCustomerBusinessTypeEnum;
import com.eastfair.venuebooking.enumeration.ExhibitionExhibitionTypeEnum;
import com.eastfair.venuebooking.enumeration.ExhibitionStateEnum;
import com.eastfair.venuebooking.enums.VenueBookingMoudleEnum;
import com.eastfair.venuebooking.exceptioncode.VenueBookingExceptionCode;
import com.eastfair.venuebooking.service.*;
import com.eastfair.venuebooking.vo.BusinessOpportunityVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * <p>
 * 业务实现类
 * 商机
 * </p>
 *
 * @author linan
 * @date 2022-06-08
 */
@Slf4j
@Service
public class BusinessOpportunityServiceImpl extends SuperServiceImpl<BusinessOpportunityMapper, BusinessOpportunity> implements BusinessOpportunityService {

    @Resource
    private BusinessOpportunityMapper businessOpportunityMapper;

    @Resource
    private CustomerMainService customerMainService;

    @Resource
    private ContactService contactService;

    @Resource
    private ContactRefService contactRefService;

    @Resource
    private ExhibitionService exhibitionService;

    @Resource
    private SaleClueService saleClueService;

    @Resource
    private ExhibitionCustomerService exhibitionCustomerService;

    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;

    @Resource
    private ExhibitionBusinessOpportunityService exhibitionBusinessOpportunityService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<BusinessOpportunity> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(BusinessOpportunity model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setTenantId(ContextUtil.getTenantId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public IPage<BusinessOpportunityVO> listBusinessOpportunityVOs(PageParams<BusinessOpportunityQuery> pageParams) {
        log.info("selectBusinessOpportunityVOList - 分页查询商机, pageParams={}", pageParams);

        handlerQueryParams(pageParams);
        Page<BusinessOpportunity> page = pageParams.buildPage();
        BusinessOpportunityQuery query = pageParams.getModel();
        QueryWrapper<BusinessOpportunity> queryWrapper = createBusinessOpportunityQueryWrapper(query);
        IPage<BusinessOpportunityVO> voPage
                = businessOpportunityMapper.listBusinessOpportunityVOs(page, queryWrapper);
        List<BusinessOpportunityVO> opportunityVOList = voPage.getRecords();
        opportunityVOList.forEach(businessOpportunityVO -> {
            // 计算未跟进天数
            if (businessOpportunityVO.getLastFollowDate() != null) {
                int notFollowDays
                        = (int) LocalDateTimeUtil.between(businessOpportunityVO.getLastFollowDate(), LocalDateTime.now(), ChronoUnit.DAYS);
                // 避免出现负数
                notFollowDays = Math.max(notFollowDays, 0);
                businessOpportunityVO.setNotFollowDays(notFollowDays);
            }
        });

        return voPage;
    }

    @Override
    public BusinessOpportunityVO getBusinessOpportunityVOById(Long id) {
        log.info("selectBusinessOpportunityVOById - id 获取商机详情, id={}", id);

        BusinessOpportunity businessOpportunity = getById(id);
        if (businessOpportunity == null) {
            throw BizException.wrap(VenueBookingExceptionCode.BUS_NOT_EXIST);
        }
        BusinessOpportunityVO businessOpportunityVO
                = BeanUtil.toBean(businessOpportunity, BusinessOpportunityVO.class);
        // 创建人/更新人 信息
        R<String> createdByNameR = userAccountServiceFeign.getName(businessOpportunity.getCreatedBy());
        businessOpportunityVO.setCreatedByName(createdByNameR.getData());
        R<String> updatedByNameR = userAccountServiceFeign.getName(businessOpportunity.getUpdatedBy());
        businessOpportunityVO.setUpdatedByName(updatedByNameR.getData());

        Exhibition exhibition = exhibitionService.selectExhibitionByOpportunityId(businessOpportunity.getId());
        if (exhibition != null) {
            businessOpportunityVO.setExhibitionId(exhibition.getId());
            businessOpportunityVO.setExhibitionName(exhibition.getExhibitionName());
            businessOpportunityVO.setExhibitionStartTime(exhibition.getExhibitionStartTime());
            businessOpportunityVO.setExhibitionEndTime(exhibition.getExhibitionEndTime());
            businessOpportunityVO.setArrangementStartTime(exhibition.getArrangementStartTime());
            businessOpportunityVO.setArrangementEndTime(exhibition.getArrangementEndTime());
            if (Objects.nonNull(exhibition.getExhibitionType()) && exhibition.getExhibitionType().eq(ExhibitionExhibitionTypeEnum.EXHIBITION)) {
                businessOpportunityVO.setDismantlingStartTime(exhibition.getDismantlingStartTime());
                businessOpportunityVO.setDismantlingEndTime(exhibition.getDismantlingEndTime());
            }
            businessOpportunityVO.setExhibitionState(exhibition.getState().getCode());
        }

        CustomerMain customerMain = customerMainService.getById(businessOpportunity.getCustomerId());
        if (customerMain != null) {
            businessOpportunityVO.setCustomerName(customerMain.getCustomerCnName());
        }

        Contact contact = contactService.getImportantContact(businessOpportunity.getId(),
                VenueBookingMoudleEnum.BUSINESS_OPPORTUNITY.getCode());
        if (contact != null) {
            businessOpportunityVO.setContactId(contact.getId());
            businessOpportunityVO.setContactName(contact.getContactName());
        }
        return businessOpportunityVO;
    }

    @Override
    public BusinessOpportunityDTO getBySaleClueId(Long saleClueId) {
        QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(BusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(saleClueId != null, BusinessOpportunity::getSaleClueId, saleClueId);
        List<BusinessOpportunity> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return null;
        }
        BusinessOpportunity businessOpportunity = list.get(0);
        BusinessOpportunityDTO businessOpportunityDTO = BeanUtil.toBean(businessOpportunity, BusinessOpportunityDTO.class);
        ExhibitionBusinessOpportunity exhibitionBusinessOpportunity = exhibitionBusinessOpportunityService.getByBusinessOpportunityId(businessOpportunity.getId());
        if (exhibitionBusinessOpportunity != null) {
            businessOpportunityDTO.setExhibitionId(exhibitionBusinessOpportunity.getExhibitionId());
        }
        return businessOpportunityDTO;
    }

    @Override
    public boolean existBusinessOpportunity(BusinessOpportunityQuery query) {
        log.info("existBusinessOpportunity - 商机是否存在, query={}", query);

        QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .in(query.getCustomerIdList() != null && !query.getCustomerIdList().isEmpty(),
                        BusinessOpportunity::getCustomerId, query.getCustomerIdList())
                .in(query.getSaleClueIdList() != null && !query.getSaleClueIdList().isEmpty(),
                        BusinessOpportunity::getSaleClueId, query.getSaleClueIdList())
        ;
        return count(queryWrapper) > 0;
    }

    @Override
    public boolean existBusinessOpportunityByCustomerIds(List<Long> customerIds) {
        BusinessOpportunityQuery query = new BusinessOpportunityQuery();
        query.setCustomerIdList(customerIds);
        return existBusinessOpportunity(query);
    }

    @Override
    public boolean existBusinessOpportunityBySaleClueIds(List<Long> saleClueIds) {
        BusinessOpportunityQuery query = new BusinessOpportunityQuery();
        query.setSaleClueIdList(saleClueIds);
        return existBusinessOpportunity(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BusinessOpportunity saveBusinessOpportunity(BusinessOpportunityDTO saveDTO) {
        log.info("saveBusinessOpportunity - 保存商机, saveDTO={}", saveDTO);
        // 线索已经被其他商机使用，则不可再使用
        if (saveDTO.getSaleClueId() != null) {
            List<Long> saleClueIds = new ArrayList<>();
            saleClueIds.add(saveDTO.getSaleClueId());
            if (existBusinessOpportunityBySaleClueIds(saleClueIds)) {
                throw BizException.wrap(VenueBookingExceptionCode.CLUE_EXIST_BUS);
            }
        }
        Exhibition existExhibition = exhibitionService.selectExhibitionByOpportunityId(saveDTO.getExhibitionId());
        if(Objects.nonNull(existExhibition)){
            boolean exhibitionCanNotUpdate = !ExhibitionStateEnum.STATE_ONE.eq(existExhibition.getState())
                    && !ExhibitionStateEnum.STATE_TWO.eq(existExhibition.getState()) && !ExhibitionStateEnum.STATE_THREE.eq(existExhibition.getState());
            if (exhibitionCanNotUpdate) {
                throw BizException.wrap(VenueBookingExceptionCode.EX_CAN_NOT_CHANGE_BUSINESS_OPPORTUNITY);
            }
        }
        BusinessOpportunity businessOpportunity = BeanUtil.toBean(saveDTO, BusinessOpportunity.class);
        save(businessOpportunity);
        // 保存联系人
        if (saveDTO.getContactId() != null) {
            ContactRef contactRef = new ContactRef();
            contactRef.setSubjectId(businessOpportunity.getId());
            contactRef.setSubjectType(VenueBookingMoudleEnum.BUSINESS_OPPORTUNITY.getCode());
            contactRef.setImportant(true);
            contactRef.setContactId(saveDTO.getContactId());
            contactRefService.save(contactRef);
        }
        // 更新展会得商机
        ExhibitionBusinessOpportunity exhibitionBusinessOpportunity = new ExhibitionBusinessOpportunity();
        exhibitionBusinessOpportunity.setExhibitionId(saveDTO.getExhibitionId());
        exhibitionBusinessOpportunity.setBusinessOpportunityId(businessOpportunity.getId());
        exhibitionBusinessOpportunityService.save(exhibitionBusinessOpportunity);
        // 保存展会客户关系
        if (saveDTO.getCustomerId() != null && saveDTO.getExhibitionId() != null && StrUtil.isNotBlank(saveDTO.getCustomerIdentity())) {
            saveDTO.setId(businessOpportunity.getId());
            saveExhibitionCustomerAndUpdateSaleCLue(saveDTO);
        }
        // 更新展会状态
        exhibitionService.updateExhibitionState(Collections.singletonList(saveDTO.getExhibitionId()));
        return businessOpportunity;
    }

    @Override
    public BusinessOpportunity saveForVenueBook(VenueBookAudit venueBookAudit, Long customerMainId, String customerMainName, Long contactId, String contactName, Long exhibitionId) {
        log.info("saveForVenueBook - 场馆预定审核通过生成商机, venueBookAudit={}, customerMainId={}, customerMainName={}, contactId={}, contactName={}, exhibitionId={}",
                venueBookAudit, customerMainId, customerMainName, contactId, contactName, exhibitionId);
        BusinessOpportunityDTO businessOpportunityDTO = new BusinessOpportunityDTO();
        businessOpportunityDTO.setBusinessTitle(venueBookAudit.getExhibitionName());
        businessOpportunityDTO.setBusinessType(venueBookAudit.getExhibitionType());
        businessOpportunityDTO.setCustomerId(customerMainId);
        businessOpportunityDTO.setCustomerName(customerMainName);
        businessOpportunityDTO.setContactId(contactId);
        businessOpportunityDTO.setContactName(contactName);
        businessOpportunityDTO.setExhibitionId(exhibitionId);
        return saveBusinessOpportunity(businessOpportunityDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBusinessOpportunity(BusinessOpportunityDTO updateDTO) {
        log.info("updateBusinessOpportunity - 更新商机, updateDTO={}", updateDTO);
        BusinessOpportunity businessOpportunity = updateBusinessOpportunityWithoutExhibitionCustomer(updateDTO);
        if (businessOpportunity == null) {
            return false;
        }
        // 保存展会客户关系
        if (updateDTO.getCustomerId() != null && updateDTO.getExhibitionId() != null && StrUtil.isNotBlank(updateDTO.getCustomerIdentity())) {
            updateDTO.setId(businessOpportunity.getId());
            saveExhibitionCustomerAndUpdateSaleCLue(updateDTO);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BusinessOpportunity updateBusinessOpportunityWithoutExhibitionCustomer(BusinessOpportunityDTO updateDTO) {
        //  准备绑定的展会已确认，就不可更改商机
        Exhibition existExhibition = exhibitionService.selectExhibitionByOpportunityId(updateDTO.getId());
        if (existExhibition != null && !existExhibition.getId().equals(updateDTO.getExhibitionId())) {
            boolean exhibitionCanNotUpdate = !ExhibitionStateEnum.STATE_ONE.eq(existExhibition.getState())
                    && !ExhibitionStateEnum.STATE_TWO.eq(existExhibition.getState()) && !ExhibitionStateEnum.STATE_THREE.eq(existExhibition.getState());
            if (exhibitionCanNotUpdate) {
                throw BizException.wrap(VenueBookingExceptionCode.EX_CAN_NOT_CHANGE_BUSINESS_OPPORTUNITY);
            }
            // 查询新展会
            Exhibition exhibition = exhibitionService.getById(updateDTO.getExhibitionId());
            if(Objects.nonNull(exhibition)){
                boolean exhibitionCanNotUpdate2 = !ExhibitionStateEnum.STATE_ONE.eq(exhibition.getState())
                        && !ExhibitionStateEnum.STATE_TWO.eq(exhibition.getState()) && !ExhibitionStateEnum.STATE_THREE.eq(exhibition.getState());
                if (exhibitionCanNotUpdate2) {
                    throw BizException.wrap(VenueBookingExceptionCode.EX_CAN_NOT_CHANGE_BUSINESS_OPPORTUNITY);
                }
            }
        }
        // 线索已经被其他商机使用，则不可再使用
        BusinessOpportunity rawBusinessOpportunity = getById(updateDTO.getId());
        if (updateDTO.getSaleClueId() != null && !updateDTO.getSaleClueId().equals(rawBusinessOpportunity.getSaleClueId())) {
            List<Long> saleClueIds = new ArrayList<>();
            saleClueIds.add(updateDTO.getSaleClueId());
            if (existBusinessOpportunityBySaleClueIds(saleClueIds)) {
                throw BizException.wrap(VenueBookingExceptionCode.CLUE_EXIST_BUS);
            }
        }
        BusinessOpportunity businessOpportunity = BeanUtil.toBean(updateDTO, BusinessOpportunity.class);
        updateById(businessOpportunity);
        if (rawBusinessOpportunity.getCustomerId().equals(updateDTO.getCustomerId())) {
            // 客户关系已存在 更新首要联系人
            ContactRefDTO contactRefUpdateDTO = new ContactRefDTO();
            contactRefUpdateDTO.setSubjectId(updateDTO.getId());
            contactRefUpdateDTO.setSubjectType(VenueBookingMoudleEnum.BUSINESS_OPPORTUNITY.getCode());
            contactRefUpdateDTO.setContactId(updateDTO.getContactId());
            contactRefUpdateDTO.setImportant(true);
            contactRefService.updateChooseContactRef(contactRefUpdateDTO);
        } else {
            // 客户更改，更新主要联系人
            // 删除所有联系人关系
            ContactRefDTO contactRefUpdateDTO = new ContactRefDTO();
            contactRefUpdateDTO.setSubjectId(updateDTO.getId());
            contactRefUpdateDTO.setSubjectType(VenueBookingMoudleEnum.BUSINESS_OPPORTUNITY.getCode());
            contactRefService.removeContactRef(contactRefUpdateDTO);
            // 保存首要联系人
            ContactRef contactRef = new ContactRef();
            contactRef.setSubjectId(businessOpportunity.getId());
            contactRef.setSubjectType(VenueBookingMoudleEnum.BUSINESS_OPPORTUNITY.getCode());
            contactRef.setContactId(updateDTO.getContactId());
            contactRef.setImportant(true);
            contactRefService.save(contactRef);
        }
        // 更新展会的商机
        UpdateWrapper<ExhibitionBusinessOpportunity> exhibitionUpdateWrapper = new UpdateWrapper<>();
        exhibitionUpdateWrapper
                .lambda()
                .eq(ExhibitionBusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(ExhibitionBusinessOpportunity::getBusinessOpportunityId, businessOpportunity.getId())
                .set(ExhibitionBusinessOpportunity::getExhibitionId, updateDTO.getExhibitionId());
        exhibitionBusinessOpportunityService.update(exhibitionUpdateWrapper);
        // 判断旧的展会 和 新绑展会的状态并更新
        exhibitionService.updateExhibitionState(Arrays.asList(Objects.nonNull(existExhibition) ? existExhibition.getId() : null, updateDTO.getExhibitionId()));
        return businessOpportunity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveExhibitionCustomerAndUpdateSaleCLue(BusinessOpportunityDTO businessOpportunityDTO) {
        // 更新展会客户关系
        ExhibitionCustomerDTO exhibitionCustomerDTO = saveExhibitionCustomer(businessOpportunityDTO);
        // 更新线索的展会客户关系
        return saleClueService.updateCustomerIdentityByBusinessOpportunity(exhibitionCustomerDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExhibitionCustomerDTO saveExhibitionCustomer(BusinessOpportunityDTO businessOpportunityDTO) {
        ExhibitionCustomerDTO exhibitionCustomerDTO = new ExhibitionCustomerDTO();
        exhibitionCustomerDTO.setExhibitionId(businessOpportunityDTO.getExhibitionId());
        exhibitionCustomerDTO.setCustomerId(businessOpportunityDTO.getCustomerId());
        exhibitionCustomerDTO.setCustomerName(businessOpportunityDTO.getCustomerName());
        exhibitionCustomerDTO.setCustomerIdentity(businessOpportunityDTO.getCustomerIdentity());
        exhibitionCustomerDTO.setBusinessId(businessOpportunityDTO.getId());
        exhibitionCustomerDTO.setBusinessType(ExhibitionCustomerBusinessTypeEnum.BUSINESS_OPPORTUNITY);
        exhibitionCustomerService.saveForSaleClueOrBusinessOpportunity(exhibitionCustomerDTO);
        return exhibitionCustomerDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFollow(BusinessOpportunityDTO updateDTO) {
        log.info("updateFollow - 更新跟进信息, updateDTO={}", updateDTO);

        UpdateWrapper<BusinessOpportunity> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .lambda()
                .eq(updateDTO.getId() != null, BusinessOpportunity::getId, updateDTO.getId())
                .set(StrUtil.isNotBlank(updateDTO.getBusinessStage()),
                        BusinessOpportunity::getBusinessStage, updateDTO.getBusinessStage())
                .set(updateDTO.getLastFollowDate() != null,
                        BusinessOpportunity::getLastFollowDate, updateDTO.getLastFollowDate())
                .set(updateDTO.getNextFollowDate() != null,
                        BusinessOpportunity::getNextFollowDate, updateDTO.getNextFollowDate());
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFollow(FollowRecordPlanSaveDTO saveDTO) {
        BusinessOpportunity businessOpportunity = getById(saveDTO.getBusinessOpportunityId());
        if (businessOpportunity == null) {
            throw BizException.wrap(VenueBookingExceptionCode.BUS_NOT_EXIST);
        }
        LocalDateTime lastFollowDate = FollowRecordService.getLastFollowDate(saveDTO.getFollowDateTime(), businessOpportunity.getLastFollowDate());
        LocalDateTime nextFollowDate = businessOpportunity.getNextFollowDate();
        if (saveDTO.getFollowPlanSaveDTO() != null) {
            nextFollowDate = FollowPlanService.getNextFollowDate(saveDTO.getFollowPlanSaveDTO().getPlanFollowDate(), businessOpportunity.getNextFollowDate());
        }
        // 更新商机
        BusinessOpportunityDTO updateDTO = new BusinessOpportunityDTO();
        updateDTO.setId(saveDTO.getBusinessOpportunityId());
        updateDTO.setBusinessStage(saveDTO.getBusinessOpportunityStage());
        updateDTO.setLastFollowDate(lastFollowDate);
        if (saveDTO.getFollowPlanSaveDTO() != null) {
            updateDTO.setNextFollowDate(nextFollowDate);
        }
        return updateFollow(updateDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBelongTo(BusinessOpportunityAssignDTO assignDTO) {
        log.info("updateBelongTo - 更新商机归属, assignDTO={}", assignDTO);
        BusinessOpportunity businessOpportunity = getById(assignDTO.getId());
        if (businessOpportunity == null) {
            throw BizException.wrap(VenueBookingExceptionCode.BUS_NOT_EXIST);
        }
        BusinessOpportunityDTO updateDTO = new BusinessOpportunityDTO();
        updateDTO.setId(assignDTO.getId());
        updateDTO.setBelongTo(assignDTO.getBelongTo());
        updateDTO.setBelongToName(assignDTO.getBelongToName());
        updateDTO.setOrgCode(assignDTO.getOrgCode());
        updateDTO.setOrgName(assignDTO.getOrgName());
        updateDTO.setLastBelongTo(businessOpportunity.getBelongTo());
        updateDTO.setLastBelongToName(businessOpportunity.getBelongToName());
        updateDTO.setLastOrgCode(businessOpportunity.getOrgCode());
        updateDTO.setLastOrgName(businessOpportunity.getOrgName());
        return updateBelongTo(updateDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBelongTo(BusinessOpportunityDTO updateDTO) {
        UpdateWrapper<BusinessOpportunity> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .lambda()
                .set(BusinessOpportunity::getLastBelongTo, updateDTO.getLastBelongTo())
                .set(BusinessOpportunity::getLastBelongToName, updateDTO.getLastBelongToName())
                .set(BusinessOpportunity::getLastOrgCode, updateDTO.getLastOrgCode())
                .set(BusinessOpportunity::getLastOrgName, updateDTO.getLastOrgName())
                .set(BusinessOpportunity::getBelongTo, updateDTO.getBelongTo())
                .set(BusinessOpportunity::getBelongToName, updateDTO.getBelongToName())
                .set(BusinessOpportunity::getOrgCode, updateDTO.getOrgCode())
                .set(BusinessOpportunity::getOrgName, updateDTO.getOrgName())
                .eq(updateDTO.getId() != null, BusinessOpportunity::getId, updateDTO.getId());
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCustomerIdentityBySaleClue(ExhibitionCustomerDTO exhibitionCustomerDTO) {
        BusinessOpportunityDTO businessOpportunityDTO = getBySaleClueId(exhibitionCustomerDTO.getBusinessId());
        if (businessOpportunityDTO == null) {
            return false;
        }
        businessOpportunityDTO.setCustomerId(exhibitionCustomerDTO.getCustomerId());
        businessOpportunityDTO.setCustomerName(exhibitionCustomerDTO.getCustomerName());
        businessOpportunityDTO.setCustomerIdentity(exhibitionCustomerDTO.getCustomerIdentity());
        businessOpportunityDTO.setExhibitionId(exhibitionCustomerDTO.getExhibitionId());
        updateBusinessOpportunityWithoutExhibitionCustomer(businessOpportunityDTO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeBusinessOpportunityByIds(List<Long> ids) {
        log.info("removeBusinessOpportunityByIds - 移除商机, ids={}", ids);
//        if (exhibitionService.existExhibitionByBusinessOpportunityIds(ids)) {
//            throw BizException.wrap(VenueBookingExceptionCode.EX_EXIST_CAN_NOT_DELETE);
//        }
        // 商机ID删除展会客户关系，并保存关联线索的展会客户关系
        exhibitionCustomerService.removeByBusinessIdsAndSaveByRelatedBusinessIds(ids, ExhibitionCustomerBusinessTypeEnum.BUSINESS_OPPORTUNITY);
        // 移除商机
        List<Long> exhibitionIds = new ArrayList<>();
        for (Long id : ids) {
            Exhibition existExhibition = exhibitionService.selectExhibitionByOpportunityId(id);
            if(Objects.nonNull(existExhibition)){
                boolean exhibitionCanNotUpdate = !ExhibitionStateEnum.STATE_ONE.eq(existExhibition.getState())
                        && !ExhibitionStateEnum.STATE_TWO.eq(existExhibition.getState()) && !ExhibitionStateEnum.STATE_THREE.eq(existExhibition.getState());
                if (exhibitionCanNotUpdate) {
                    throw BizException.wrap(VenueBookingExceptionCode.EX_CAN_NOT_CHANGE_BUSINESS_OPPORTUNITY);
                }
                exhibitionIds.add(existExhibition.getId());
            }
        }
        List<BusinessOpportunity> businessOpportunities = listByIds(ids);
        removeByIdsOfLogic(businessOpportunities);
        // 移除联系人关联
        ContactRefDTO updateDTO = new ContactRefDTO();
        updateDTO.setSubjectIds(ids);
        updateDTO.setSubjectType(VenueBookingMoudleEnum.BUSINESS_OPPORTUNITY.getCode());
        contactRefService.removeContactRef(updateDTO);
        // 更新展会
        UpdateWrapper<ExhibitionBusinessOpportunity> exhibitionUpdateWrapper = new UpdateWrapper<>();
        exhibitionUpdateWrapper
                .lambda()
                .in(ExhibitionBusinessOpportunity::getBusinessOpportunityId, ids)
                .eq(ExhibitionBusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .set(ExhibitionBusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_YES);
        exhibitionBusinessOpportunityService.update(exhibitionUpdateWrapper);
        // 更新展会状态
        exhibitionService.updateExhibitionState(exhibitionIds);
        return true;
    }

    private QueryWrapper<BusinessOpportunity> createBusinessOpportunityQueryWrapper(BusinessOpportunityQuery query) {
        QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq(Objects.nonNull(query.getId()), "bo.id", query.getId())
                .and(StrUtil.isNotBlank(query.getKeyword()), bQueryWrapper -> bQueryWrapper
                        .like("bo.business_title", query.getKeyword())
                        .or()
                        .like("cm.customer_cn_name", query.getKeyword()))
                .eq(StrUtil.isNotBlank(query.getBusinessType()), "" +
                        "bo.business_type", query.getBusinessType())
                .eq(StrUtil.isNotBlank(query.getBusinessProperty()), "" +
                        "bo.business_property", query.getBusinessProperty())
                .between(StrUtil.isNotBlank(query.getEstimateSignBillStart())
                                && StrUtil.isNotBlank(query.getEstimateSignBillEnd()),
                        "bo.estimate_sign_bill", query.getEstimateSignBillStart(), query.getEstimateSignBillEnd())
                .eq(query.getCustomerId() != null, "bo.customer_id", query.getCustomerId())
                .eq(query.getExhibitionId() != null, "ex.id", query.getExhibitionId())
                .eq(query.getBelongTo() != null, "bo.belong_to", query.getBelongTo())
                .like(StrUtil.isNotBlank(query.getBelongToName()), "bo.belong_to_name", query.getBelongToName())
                .isNotNull(query.getIsDeal() != null && query.getIsDeal(), "conm.id")
                .eq("bo.is_deleted", BusinessConstant.DELETE_NO)
                .groupBy("bo.id");
        return queryWrapper;
    }

    public void handlerQueryParams(PageParams<BusinessOpportunityQuery> params) {
        if (StrUtil.isBlank(params.getSort()) || StrUtil.isBlank(params.getOrder())) {
            params.setSort("createTime");
            params.setOrder("descending");
        }
    }


    /**
     * 获取全部商机
     *
     * @return
     */
    @Override
    public List<BusinessOpportunity> getBusinessOpportunityList(SalesAnalysisDTO salesAnalysisDTO) {
        //查询展厅列表
        QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Strings.isNotBlank(salesAnalysisDTO.getSalesStage()), BusinessOpportunity::getSalesStage, salesAnalysisDTO.getSalesStage())
                .eq(Objects.nonNull(salesAnalysisDTO.getDepartmentId()), BusinessOpportunity::getOrgCode, salesAnalysisDTO.getDepartmentId())
                .eq(Objects.nonNull(salesAnalysisDTO.getPersonnelId()), BusinessOpportunity::getBelongTo, salesAnalysisDTO.getPersonnelId())
                .between(Objects.nonNull(salesAnalysisDTO.getStartTime())
                                && Objects.nonNull(salesAnalysisDTO.getEndTime()),
                        BusinessOpportunity::getCreateTime, salesAnalysisDTO.getStartTime(), salesAnalysisDTO.getEndTime());

        List<BusinessOpportunity> list = this.list(queryWrapper);
        return list;
    }

    /**
     * 查询商机销售阶段下的数据集合
     *
     * @param pageParams
     * @return
     */
    @Override
    public IPage<BusinessOpportunityVO> getBusinessOpportunityPageList(PageParams<SalesAnalysisDTO> pageParams) {
        Page<BusinessOpportunity> page = new Page<>(pageParams.getCurrent(), pageParams.getSize());
        //查询展厅列表
        QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Strings.isNotBlank(pageParams.getModel().getSalesStage()), BusinessOpportunity::getSalesStage, pageParams.getModel().getSalesStage())
                .eq(Objects.nonNull(pageParams.getModel().getDepartmentId()), BusinessOpportunity::getOrgCode, pageParams.getModel().getDepartmentId())
                .eq(Objects.nonNull(pageParams.getModel().getPersonnelId()), BusinessOpportunity::getBelongTo, pageParams.getModel().getPersonnelId())
                .between(Objects.nonNull(pageParams.getModel().getStartTime())
                                && Objects.nonNull(pageParams.getModel().getEndTime()),
                        BusinessOpportunity::getCreateTime, pageParams.getModel().getStartTime(), pageParams.getModel().getEndTime());
        page = page(page, queryWrapper);
        Page<BusinessOpportunityVO> businessOpportunityVOPage = ConvertUtil.convertPage(page, BusinessOpportunityVO.class);
        return businessOpportunityVOPage;
    }

    @Override
    public long countBusinessOpportunityByCustomerId(Long customerId) {
        QueryWrapper<BusinessOpportunity> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(BusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(customerId != null, BusinessOpportunity::getCustomerId, customerId);
        return count(queryWrapper);
    }
}
